package com.yingxin.yxerp.module.activiti.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yingxin.yx.framework.commons.activiti.ApprovalStatus;
import com.yingxin.yx.framework.commons.activiti.def.TaskDef;
import com.yingxin.yx.framework.commons.activiti.dto.ActivitiInstanceDto;
import com.yingxin.yx.framework.commons.activiti.dto.ActivitiInstanceQueryDto;
import com.yingxin.yx.framework.commons.activiti.dto.UserProcessDto;
import com.yingxin.yx.framework.commons.activiti.dto.UserTaskDto;
import com.yingxin.yx.framework.commons.activiti.enums.FormKey;
import com.yingxin.yx.framework.commons.dto.AttachmentDto;
import com.yingxin.yx.framework.commons.dto.PageOut;
import com.yingxin.yx.framework.commons.enums.BusinessType;
import com.yingxin.yx.framework.commons.exception.BizException;
import com.yingxin.yx.framework.commons.helper.ListHelper;
import com.yingxin.yx.framework.commons.vo.CommonRespVo;
import com.yingxin.yx.framework.mybatisplus.PageHelper;
import com.yingxin.yx.framework.user.core.IUserSupport;
import com.yingxin.yxerp.module.activiti.api.ProcessQueryService;
import com.yingxin.yxerp.module.activiti.entity.ActivitiBizInfo;
import com.yingxin.yxerp.module.activiti.entity.builder.ProcessInstanceDtoBuilder;
import com.yingxin.yxerp.module.activiti.entity.builder.TaskInstanceDtoBuilder;
import com.yingxin.yxerp.module.activiti.mapper.ActivitiBizInfoMapper;
import com.yingxin.yxerp.module.attachment.constant.AttachConst;
import com.yingxin.yxerp.module.attachment.service.IAttachmentService;
import com.yingxin.yxerp.module.organization.entity.User;
import com.yingxin.yxerp.module.organization.service.IUserService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class ActivitiUserQueryService implements ProcessQueryService {

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserSupport userSupport;

    @Autowired
    private ActivitiProcessService activitiProcessService;


    @Autowired
    private IActivitiBizInfoService activitiBizInfoService;

    @Autowired
    @SuppressWarnings("all")
    private ActivitiBizInfoMapper activitiBizInfoMapper;

    @Autowired
    private IAttachmentService attachmentService;

    // @Autowired
    // private IFormStructureService formStructureService;

    /**
     * 查看详情 或者 cc
     */
    public ActivitiInstanceDto getProcessInstance(String instanceId) {
        // processInstance
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId).singleResult();
        if (processInstance == null) {
            throw new BizException("无法查看这个申请流程");
        }
        // applicantUser
        User applicantUser = userService.getById(processInstance.getStartUserId());
        // bizInfo
        ActivitiBizInfo bizInfo = activitiBizInfoService.getById(processInstance.getBusinessKey());
        List<ActivitiInstanceDto> allTask = findAllTaskByProcessInstance(applicantUser, bizInfo);
        // 封装
        ActivitiInstanceDto dto = new ProcessInstanceDtoBuilder().add(bizInfo).add(applicantUser).addHitTasks(allTask).getProcessInstance();
        dto.setFormKey(FormKey.READ_ONLY.getKey());
        return dto;
    }

    /**
     * 查看流程详情 By Applicant
     */
    public ActivitiInstanceDto getStartProc(String applicant, String instanceId) {
        // applicantUser
        User applicantUser = userService.getById(applicant);
        // processInstance
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId).startedBy(applicant).singleResult();
        if (processInstance == null) {
            throw new BizException("无法查看这个申请流程");
        }
        ActivitiBizInfo bizInfo = activitiBizInfoService.getById(processInstance.getBusinessKey());
        // taskList
        List<ActivitiInstanceDto> allTask = findAllTaskByProcessInstance(applicantUser, bizInfo);
        // 封装
        ActivitiInstanceDto dto = new ProcessInstanceDtoBuilder().add(bizInfo).add(applicantUser).addHitTasks(allTask).getProcessInstance();
        if (StringUtils.isBlank(bizInfo.getFirstAssigneeInfo())) {
            dto.setFormKey(FormKey.CANCEL_ONLY.getKey());
        } else {
            dto.setFormKey(FormKey.READ_ONLY.getKey());
        }
        return dto;
    }


    public PageOut<ActivitiInstanceDto> pageUserProcess(String applicant, ActivitiInstanceQueryDto queryDto) {
        // applicant
        User user = userService.getById(applicant);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        queryDto.setUserId(user.getId());
        IPage<UserProcessDto> page = activitiBizInfoMapper.pageUserProcess(PageHelper.in(queryDto), queryDto);
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<UserProcessDto> processList = page.getRecords();
            // 封装
            for (UserProcessDto proc : processList) {
                ActivitiInstanceDto dto = new ProcessInstanceDtoBuilder().add(proc).add(user).getProcessInstance();
                dtoList.add(dto);
            }
        }
        return new PageOut(page.getCurrent(), page.getSize(), page.getPages(), page.getTotal(), dtoList);
    }


    /**
     * PendingTask By Assignee And Id
     * @param assignee 审核人id / 查看人id
     * @param taskId 流程Id
     * @param bizInfo 节点信息
     * @param applicant  申请信息
     * @return
     */
    public ActivitiInstanceDto getPendingTaskByAssignee(String assignee, String taskId, ActivitiBizInfo bizInfo, User applicant) {
        // 任务
        Task task = activitiProcessService.getTaskByAssigneeAndId(taskId, assignee);
        if (task == null) {
            throw new BizException("无法查看该任务");
        }
        // 流程实例
        if (bizInfo == null) {
            bizInfo = activitiBizInfoService.getById(task.getBusinessKey());
        }
        if (applicant == null) {
            applicant = userService.getById(bizInfo.getApplicantId());
        }
        List<ActivitiInstanceDto> allTask = findAllTaskByProcessInstance(applicant, bizInfo);
        Map<String, ActivitiInstanceDto> allTaskMap = ListHelper.toMap(ActivitiInstanceDto::getTaskId, allTask);
        // 任务
        ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(applicant).addHitTasks(allTask).getTask();
        dto.setAssigneeName(allTaskMap.get(dto.getTaskId()).getAssigneeName());
        dto.setTaskApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
        // 任务操作定义
        List<TaskDef> taskDefList = JSON.parseArray(bizInfo.getBpmnTask(), TaskDef.class);
        Map<String, TaskDef> taskDefMap = ListHelper.toMap(TaskDef::getElementId, taskDefList);
        TaskDef taskDef = taskDefMap.get(task.getTaskDefinitionKey());
        if (taskDef != null) {
            dto.setActions(taskDef.getActions());
            dto.setActionDefList(taskDef.getActionDefList());
        }
        dto.setIncomeSubtract(taskDef.getIncomeSubtract());
        dto.setIsAppApproval(taskDef.getIsAppApproval());
        // dto.setCustomFormId(taskDef.getCustomFormId());
        // dto.setCustomFormContent(formStructureService.getItemVo(taskDef.getCustomFormId()));
        return dto;
    }

    /**
     * 待审核
     * PendingTask By Assignee
     */
    public PageOut<ActivitiInstanceDto> pagePendingTask(String assignee, ActivitiInstanceQueryDto queryDto) {
        User user = userService.getById(assignee);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        queryDto.setUserId(user.getId());
        queryDto.setGroupId(user.getDeptId());
        IPage<UserTaskDto> page = activitiBizInfoMapper.pagePendingTask(PageHelper.in(queryDto), queryDto);
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<UserTaskDto> taskList = page.getRecords();
            Set<String> startUserIds = ListHelper.toSet(UserTaskDto::getApplicantId, taskList);
            List<User> startUserList = userService.listByIds(startUserIds);
            Map<String, User> startUserMap = ListHelper.toMap(User::getId, startUserList);
            // 封装 taskDtoList
            for (UserTaskDto task : taskList) {
                User startUser = startUserMap.get(task.getApplicantId());
                ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(startUser).getTask();
                dto.setTaskApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
                dtoList.add(dto);
            }
        }
        return new PageOut(page.getCurrent(), page.getSize(), page.getPages(), page.getTotal(), dtoList);
    }

    /**
     * 查看所有待办任务
     */
    public PageOut<ActivitiInstanceDto> pageAllTask(ActivitiInstanceQueryDto queryDto) {
        IPage<UserTaskDto> page = activitiBizInfoMapper.pageAllTask( PageHelper.in(queryDto), queryDto );
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<UserTaskDto> taskList = page.getRecords();
            Set<String> startUserIds = ListHelper.toSet(UserTaskDto::getApplicantId, taskList);
            List<User> startUserList = userService.listByIds(startUserIds);
            Map<String, User> startUserMap = ListHelper.toMap(User::getId, startUserList);
            // 封装 taskDtoList
            for (UserTaskDto task : taskList) {
                User startUser = startUserMap.get(task.getApplicantId());
                ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(startUser).getTask();
                dto.setTaskApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
                dtoList.add(dto);
            }
        }
        return new PageOut(page.getCurrent(), page.getSize(), page.getPages(), page.getTotal(), dtoList);
    }

    /**
     * CompletedTask By Assignee And Id
     */
    public ActivitiInstanceDto getCompletedTask(String assignee, String taskId) {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskAssignee(assignee).taskId(taskId).singleResult();
        if (task == null) {
            throw new BizException("无法查看该任务");
        }
        ActivitiBizInfo bizInfo = activitiBizInfoService.getByProcessInstanceId(task.getProcessInstanceId());
        // startUser
        User startUser = userService.getById(bizInfo.getApplicantId());
        // 流程已经执行到的任务
        List<ActivitiInstanceDto> allTask = findAllTaskByProcessInstance(startUser, bizInfo);
        Map<String, ActivitiInstanceDto> allTaskMap = ListHelper.toMap(ActivitiInstanceDto::getTaskId, allTask);
        // 任务
        ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser).addHitTasks(allTask)
                .taskApprovalStatus().addComments(taskService.getTaskComments(task.getId())).getTask();
        dto.setFormKey(FormKey.READ_ONLY.getKey());
        dto.setAssigneeName(allTaskMap.get(dto.getTaskId()).getAssigneeName());
        return dto;
    }


    public PageOut<ActivitiInstanceDto> pageCompletedTask(String assignee, ActivitiInstanceQueryDto queryDto) {
        User user = userService.getById(assignee);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        queryDto.setUserId(user.getId());
        IPage<UserTaskDto> page = activitiBizInfoMapper.pageCompletedTask(PageHelper.in(queryDto), queryDto);
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<UserTaskDto> taskList = page.getRecords();
            // 查询 startUser
            Set<String> startUserIds = ListHelper.toSet(UserTaskDto::getApplicantId, taskList);
            List<User> startUserList = userService.listByIds(startUserIds);
            Map<String, User> startUserMap = ListHelper.toMap(User::getId, startUserList);
            // 查询 assignee
            Set<String> assigneeIds = ListHelper.toSet(UserTaskDto::getAssigneeId, taskList);
            List<User> assigneeList = userService.listByIds(assigneeIds);
            Map<String, User> assigneeMap = ListHelper.toMap(User::getId, assigneeList);
            // 封装
            for (UserTaskDto task : taskList) {
                User startUser = startUserMap.get(task.getApplicantId());
                User assigneeUser = assigneeMap.get(task.getAssigneeId());
                ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(startUser)
                        .addAssigneeName(assigneeUser).taskApprovalStatus()
                        .getTask();
                dtoList.add(dto);
            }
        }
        return new PageOut(page.getCurrent(), page.getSize(), page.getPages(), page.getTotal(), dtoList);
    }


    /**
     * 查询 all任务 by ProcessInstanceId
     */
    private List<ActivitiInstanceDto> findAllTaskByProcessInstance(User startUser, ActivitiBizInfo bizInfo) {
        // 流程实例的任务
        List<HistoricTaskInstance> taskList = activitiProcessService.listHistoricTaskByProcessInstanceId(bizInfo.getProcessInstanceId());
        // assigneeList
        Set<String> assigneeIds = ListHelper.toSet(HistoricTaskInstance::getAssignee, taskList);
        List<User> assigneeList = userService.listByIds(assigneeIds);
        Map<String, User> assigneeMap = ListHelper.toMap(User::getId, assigneeList);
        // 附件
        List<AttachmentDto> attachments = attachmentService.listByBiz(bizInfo.getBizId(), BusinessType.AUDIT_TASK);
        Map<String, List<AttachmentDto>> attachmentGroupingMap = attachments.stream()
                .collect(Collectors.groupingBy(AttachmentDto::getBusinessAttr));
        // 封装 taskDtoList
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        for (HistoricTaskInstance task : taskList) {
            // 任务结束，并且没有审核人的跳过；这种是使用了审核通过并且结束流程的功能
            if (task.getEndTime() != null && StringUtils.isEmpty(task.getAssignee())) {
                continue;
            }
            User assigneeUser = assigneeMap.get(task.getAssignee());
            ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser)
                    .addAssigneeName(assigneeUser).taskApprovalStatus().addComments(taskService.getTaskComments(task.getId())).getTask();
            // 多个审核人
            if (StringUtils.isBlank(dto.getAssigneeId())) {
                dto.setAssigneeName(activitiProcessService.getCandidateAssigneeNameByTask(dto.getTaskId()));
            }
            // 签名
            if (ApprovalStatus.APPROVED.getStatus().equals(dto.getTaskApprovalStatus())) {
                if (assigneeUser != null) {
                    AttachmentDto attachment = attachmentService.getByBiz(assigneeUser.getId(), BusinessType.USER, AttachConst.SIGN);
                    if (attachment != null) {
                        dto.setAssigneeSignUrl(attachment.getAttachmentUrl());
                    }
                }
            }
            // 附件
            dto.setTaskAttachmentList(attachmentGroupingMap.get(task.getId()));
            dtoList.add(dto);
        }
        return dtoList;
    }


    /**
     * getProcessByBusinessKey
     * businessKey 单据ID
     */
    public ActivitiInstanceDto getProcessByBusinessKey(String businessKey) {
        // assignee
        String assigneeId = userSupport.getUserId();
        User assigneeUser = userService.getById(assigneeId);
        // bizInfo 自定义信息表
        ActivitiBizInfo bizInfo = activitiBizInfoService.getById(businessKey);
        if (bizInfo == null) {
            return new ActivitiInstanceDto();
        }
        // userTask 节点信息
        UserTaskDto userTask = activitiBizInfoMapper.getPendingTask(bizInfo.getBizType(), bizInfo.getBizId(),
                assigneeUser.getId(), assigneeUser.getDeptId());
        // applicantUser 申请人信息
        User applicantUser = userService.getById(bizInfo.getApplicantId());
        if (userTask != null) {
            return getPendingTaskByAssignee(assigneeUser.getId(), userTask.getTaskId(), bizInfo, applicantUser);
        } else {
            // bizInfo
            List<ActivitiInstanceDto> allTask = findAllTaskByProcessInstance(applicantUser, bizInfo);
            ActivitiInstanceDto dto = new ProcessInstanceDtoBuilder().add(bizInfo).add(applicantUser).addHitTasks(allTask).getProcessInstance();
            dto.setFormKey(FormKey.READ_ONLY.getKey());
            return dto;
        }
    }


    /**
     * collectTaskId
     */
    public <T> void collectTaskId(List<T> list, Function<T, String> function, BusinessType... businessTypeList) {
        User user = userService.getById(userSupport.getUserId());
        for (BusinessType businessType : businessTypeList) {
            List<UserTaskDto> userTaskList = listPendingTask(user, businessType);
            Map<String, String> userTaskMap = ListHelper.toMap(UserTaskDto::getBusinessKey, UserTaskDto::getTaskId, userTaskList);
            for (T t : list) {
                if (t instanceof CommonRespVo) {
                    String id = function.apply(t);
                    String taskId = userTaskMap.get(id);
                    if (StringUtils.isNotBlank(taskId)) {
                        CommonRespVo bill = (CommonRespVo) t;
                        bill.setTaskId(taskId);
                    }
                }
            }
        }
    }

    /**
     * listPendingTask
     */
    public List<UserTaskDto> listPendingTask(User user, BusinessType bizType) {
        if (user == null) {
            return new ArrayList<>();
        }
        ActivitiInstanceQueryDto queryDto = new ActivitiInstanceQueryDto();
        queryDto.setUserId(user.getId());
        queryDto.setGroupId(user.getDeptId());
        queryDto.setBizType(bizType == null ? null : bizType.getType());
        return activitiBizInfoMapper.listPendingTask(queryDto);
    }



    /*
    public PageOut<ActivitiInstanceDto> listCompletedTaskByAssignee(String assignee, ActivitiInstanceQueryDto queryDto) {
        //全是历史的
        int firstResult = (queryDto.getPageNo() - 1) * queryDto.getPageSize();
        // count
        long count = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(assignee).finished().count();
        // taskList
        List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(assignee).finished().orderByTaskCreateTime().desc().listPage(firstResult, queryDto.getPageSize());
        if (CollectionUtil.isEmpty(taskList)) {
            return new PageOut(new ArrayList());
        }
        Set<String> processInstanceIds = ListHelper.toSet(HistoricTaskInstance::getProcessInstanceId, taskList);
        List<ActivitiBizInfo> bizInfoList = activitiBizInfoService.listByProcessInstanceIds(processInstanceIds);
        Map<String, ActivitiBizInfo> bizInfoMap = ListHelper.toMap(ActivitiBizInfo::getProcessInstanceId, bizInfoList);
        // 查询流程实例
        // Set<String> processInstanceIds = ListHelper.toSet(HistoricTaskInstance::getProcessInstanceId, taskList);
        // List<HistoricProcessInstance> processInstanceList = activitiProcessService.listHistoricProcessInstanceByIds(processInstanceIds);
        // Map<String, HistoricProcessInstance> processInstanceMap = ListHelper.toMap(HistoricProcessInstance::getId, processInstanceList);
        // 查询 startUser
        Set<String> startUserIds = ListHelper.toSet(ActivitiBizInfo::getApplicantId, bizInfoList);
        List<User> startUserList = userService.listByIds(startUserIds);
        Map<String, User> startUserMap = ListHelper.toMap(User::getId, startUserList);
        // 查询 assignee
        Set<String> assigneeIds = ListHelper.toSet(HistoricTaskInstance::getAssignee, taskList);
        List<User> assigneeList = userService.listByIds(assigneeIds);
        Map<String, User> assigneeMap = ListHelper.toMap(User::getId, assigneeList);
        // 封装
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        for (HistoricTaskInstance task : taskList) {
            //  HistoricProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
            ActivitiBizInfo bizInfo = bizInfoMap.get(task.getProcessInstanceId());
            User startUser = null;
            if (bizInfo != null) {
                startUser = startUserMap.get(bizInfo.getApplicantId());
            }
            User assigneeUser = assigneeMap.get(task.getAssignee());
            ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser)
                    .addAssigneeName(assigneeUser).taskApprovalStatus()
                    .addComments(taskService.getTaskComments(task.getId())).getTask();
            // findCandidateInfo(dto);
            dtoList.add(dto);
        }
        long remainder = count % queryDto.getPageSize();
        PageOut pageOut = new PageOut();
        pageOut.setPageNo(queryDto.getPageNo());
        pageOut.setPageSize(queryDto.getPageSize());
        pageOut.setPageCount(remainder == 0 ? count / queryDto.getPageSize() : count / queryDto.getPageSize() + 1);
        pageOut.setTotalCount(count);
        pageOut.setRows(dtoList);
        return pageOut;
    }



    public PageOut<ActivitiInstanceDto> listPendingTaskByAssignee(String assignee, ActivitiInstanceQueryDto queryDto) {
        User user = userService.getById(assignee);
        if (user == null) {
            throw new BizException("用户不存在");
        }
        // taskList
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(assignee).list();
        // candidateUserTaskList
        List<Task> candidateUserTaskList = taskService.createTaskQuery().taskCandidateUser(assignee).list();
        taskList.addAll(candidateUserTaskList);
        // candidateGroupTaskList
        if (StringUtils.isNotEmpty(user.getDeptId())) {
            List<Task> candidateGroupTaskList = taskService.createTaskQuery().taskCandidateGroup(user.getDeptId()).list();
            taskList.addAll(candidateGroupTaskList);
        }
        if (CollectionUtil.isEmpty(taskList)) {
            return new PageOut(new ArrayList());
        }
        long count = taskList.size();
        // 排序
        taskList = taskList.stream().sorted(Comparator.comparing(Task::getCreateTime).reversed()).collect(Collectors.toList());
        // 分页
        taskList = taskList.stream().skip((queryDto.getPageNo() - 1) * queryDto.getPageSize()).limit(queryDto.getPageSize()).
                collect(Collectors.toList());
        List<ActivitiBizInfo> bizInfoList = activitiBizInfoService.listByBizIds(ListHelper.toList(Task::getBusinessKey, taskList));
        Map<String, ActivitiBizInfo> bizInfoMap = ListHelper.toMap(ActivitiBizInfo::getBizId, bizInfoList);
        // 查询流程实例
        // Set<String> processInstanceIds = ListHelper.toSet(Task::getProcessInstanceId, taskList);
        // List<HistoricProcessInstance> processInstanceList = activitiProcessService.listHistoricProcessInstanceByIds(processInstanceIds);
        // Map<String, HistoricProcessInstance> processInstanceMap = ListHelper.toMap(HistoricProcessInstance::getId, processInstanceList);
        // 查询 startUser
        Set<String> startUserIds = ListHelper.toSet(ActivitiBizInfo::getApplicantId, bizInfoList);
        List<User> startUserList = userService.listByIds(startUserIds);
        Map<String, User> startUserMap = ListHelper.toMap(User::getId, startUserList);
        // 封装 taskDtoList
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        for (Task task : taskList) {
            ActivitiBizInfo bizInfo = bizInfoMap.get(task.getBusinessKey());
            User startUser = null;
            if (bizInfo != null) {
                startUser = startUserMap.get(bizInfo.getApplicantId());
            }
            ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser).getTask();
            dto.setTaskApprovalStatus(ApprovalStatus.PENDING_APPROVAL.getStatus());
            // findCandidateInfo(dto);
            dtoList.add(dto);
        }
        long remainder = count % queryDto.getPageSize();
        PageOut pageOut = new PageOut();
        pageOut.setPageNo(queryDto.getPageNo());
        pageOut.setPageSize(queryDto.getPageSize());
        pageOut.setPageCount(remainder == 0 ? count / queryDto.getPageSize() : count / queryDto.getPageSize() + 1);
        pageOut.setTotalCount(count);
        pageOut.setRows(dtoList);
        return pageOut;
    }


    public PageOut<ActivitiInstanceDto> listProcessInstanceByApplicant(String applicant, ActivitiInstanceQueryDto queryDto) {
        int firstResult = (queryDto.getPageNo() - 1) * queryDto.getPageSize();
        // applicant
        User applicantUser = userService.getById(applicant);
        // count
        long count = historyService.createHistoricProcessInstanceQuery()
                .startedBy(applicant).count();
        // processInstanceList
        List<HistoricProcessInstance> processInstanceList = historyService.createHistoricProcessInstanceQuery()
                .startedBy(applicant).orderByProcessInstanceStartTime().desc().listPage(firstResult, queryDto.getPageSize());
        if (CollectionUtil.isEmpty(processInstanceList)) {
            return new PageOut(new ArrayList());
        }
        // bizInfoList
        List<String> bizIds = ListHelper.toList(HistoricProcessInstance::getBusinessKey, processInstanceList);
        List<ActivitiBizInfo> bizInfoList = activitiBizInfoService.listByBizIds(bizIds);
        Map<String, ActivitiBizInfo> bizInfoMap = ListHelper.toMap(ActivitiBizInfo::getBizId, bizInfoList);
        // 封装
        List<ActivitiInstanceDto> list = new ArrayList<>();
        for (HistoricProcessInstance processInstance : processInstanceList) {
            ActivitiBizInfo bizInfo = bizInfoMap.get(processInstance.getBusinessKey());
            ActivitiInstanceDto dto = new ProcessInstanceDtoBuilder().add(bizInfo).add(applicantUser).getProcessInstance();
            list.add(dto);
        }
        long remainder = count % queryDto.getPageSize();
        PageOut pageOut = new PageOut();
        pageOut.setPageNo(queryDto.getPageNo());
        pageOut.setPageSize(queryDto.getPageSize());
        pageOut.setPageCount(remainder == 0 ? count / queryDto.getPageSize() : count / queryDto.getPageSize() + 1);
        pageOut.setTotalCount(count);
        pageOut.setRows(list);
        return pageOut;
    }

    private List<ActivitiInstanceDto> findAllTaskByProcessInstance(User startUser, ActivitiBizInfo bizInfo){
        Map<String, ActivitiInstanceDto> map = new HashMap<>();
        List<ActivitiInstanceDto> historyList = findHistoricTaskByProcessInstance(startUser, bizInfo);
        for(ActivitiInstanceDto dto : historyList){
            map.put(dto.getTaskId(), dto);
        }
        List<ActivitiInstanceDto> list = findTaskByProcessInstance(startUser, bizInfo);
        for(ActivitiInstanceDto dto : list){
            map.put(dto.getTaskId(), dto);
        }
        // assigneeList
        Set<String> assigneeIds = ListHelper.toSet(ActivitiInstanceDto::getAssigneeId, map.values());
        List<User> assigneeList = userService.listByIds(assigneeIds);
        Map<String, User> assigneeMap = ListHelper.toMap(User::getId, assigneeList);

        // 附件
        List<AttachmentDto> attachments = attachmentService.listByBiz(bizInfo.getBizId(), BusinessType.AUDIT_TASK);
        Map<String, List<AttachmentDto>> attachmentGroupingMap = attachments.stream()
                .collect(Collectors.groupingBy(AttachmentDto::getBusinessAttr));

        for(ActivitiInstanceDto dto : map.values()){
            User assigneeUser = assigneeMap.get(dto.getAssigneeId());
            if (assigneeUser != null) {
                dto.setAssigneeName(assigneeUser.getStaffName());
            }
            // 多个审核人
            if (StringUtils.isBlank(dto.getAssigneeId())) {
                dto.setAssigneeName(activitiProcessService.getCandidateAssigneeNameByTask(dto.getTaskId()));
            }
            // 签名
            if (ApprovalStatus.APPROVED.getStatus().equals(dto.getTaskApprovalStatus())) {
                AttachmentDto attachment = attachmentService.getByBiz(dto.getAssigneeId(), BusinessType.USER, AttachConst.SIGN);
                if (attachment != null) {
                    dto.setAssigneeSignUrl(attachment.getAttachmentUrl());
                }
            }
            // 附件
            dto.setTaskAttachmentList(attachmentGroupingMap.get(dto.getTaskId()));
        }
        List<ActivitiInstanceDto> result = new ArrayList<>(map.values());
        result.sort(Comparator.comparing(ActivitiInstanceDto::getCreateTime));
        return result;
    }

    private List<ActivitiInstanceDto> findTaskByProcessInstance(User startUser, ActivitiBizInfo bizInfo) {
        // 流程实例的任务
        List<Task> taskList = activitiProcessService.listTaskByProcessInstanceId(bizInfo.getProcessInstanceId());
        // 封装 taskDtoList
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        for (Task task : taskList) {
            ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser)
                    .taskApprovalStatus().addComments(taskService.getTaskComments(task.getId())).getTask();
            dto.setCreateTime(task.getCreateTime());
            dtoList.add(dto);
        }
        return dtoList;
    }


    private List<ActivitiInstanceDto> findHistoricTaskByProcessInstance(User startUser, ActivitiBizInfo bizInfo) {
        // 流程实例的任务
        List<HistoricTaskInstance> taskList = activitiProcessService.listHistoricTaskByProcessInstanceId(bizInfo.getProcessInstanceId());
        // 封装 taskDtoList
        List<ActivitiInstanceDto> dtoList = new ArrayList<>();
        for (HistoricTaskInstance task : taskList) {
            // 任务结束，并且没有审核人的跳过；这种是使用了审核通过并且结束流程的功能
            if (task.getEndTime() != null && StringUtils.isEmpty(task.getAssignee())) {
                continue;
            }
            ActivitiInstanceDto dto = new TaskInstanceDtoBuilder().add(task).add(bizInfo).add(startUser)
                    .taskApprovalStatus().addComments(taskService.getTaskComments(task.getId())).getTask();
            dto.setCreateTime(task.getCreateTime());
            dtoList.add(dto);
        }
        return dtoList;
    }

     */
}